package symboltable;

import syntaxtree.Type;
import syntaxtree.Formal;

import java.util.Hashtable;
import java.util.Vector;

public class Method {
	private Vector<Symbol> params_symbol;
	private Vector<Type> params_type;
	private Hashtable<Symbol, Type> variables;
	
	private Type return_type;
	private Symbol symbol;
	
	// Instantiates a method with its return type, symbol, and list of arguments
	public Method(Type ret, Symbol  n, Vector<Formal> par) 
	{
		params_symbol = new Vector<Symbol>();
		params_type = new Vector<Type>();
		variables = new Hashtable<Symbol,Type>();
		
		return_type = ret;
		symbol = n;
		for (Formal arg : par) {
			variables.put(Symbol.symbol(arg.i.s), arg.t);
			params_symbol.add(Symbol.symbol(arg.i.s));
			params_type.add(arg.t);
		}
	}
	
	public Type get_return_type()
	{
		return return_type;
	}
	
	// Return true in case the given list of types equals the param types of this method
	public boolean compare_params_type(Vector<Formal> cp)
	{
		if (cp.size() != params_type.size()) {
			return false;
		}
		boolean equal = true;
		for(int i = 0; i < cp.size(); i++) {
			if (!params_type.get(i).equals(params_type.get(i))) {
				equal = false;
			}
		}
		return equal;
	}
	
	public boolean contains_variable(Symbol s)
	{
		// If the variable is already declared in this method or in the parameters list
		return variables.containsKey(s);
	}
	
	public Type get_variable_type(Symbol s)
	{
		if (params_symbol.contains(s)) {
			for (int i = 0; i < params_symbol.size(); i++) {
				if (params_symbol.get(i).equals(s)) {
					return params_type.get(i);
				}
			}
		} else if(variables.containsKey(s)){
			return variables.get(s);
		} else {
			return null;
		}
		return null;
	}
	
	public void add_variable(Symbol s, Type t)
	{
		// Add a definition for a local variable
		variables.put(s, t);
	}
}
